package cn.buddha.jesj.thread.jvm;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author shihao
 * @description jstack 案例
 */
@Slf4j
public class JstackTest {

    public static void main(String[] args) {
//        deathLock();

        cpu();
    }

    private static final Object LOCK = new Object();

    private static void cpu() {
        ExecutorService es = Executors.newFixedThreadPool(2);

        es.execute(new Task());
        es.execute(new Task());
    }

    static class Task implements Runnable {
        @Override
        public void run() {
            synchronized (LOCK) {
                long sum = 0L;
                while (true) {
                    sum += 1;
                }
            }
        }
    }

    private static Lock lock1 = new ReentrantLock(false);
    private static Lock lock2 = new ReentrantLock(false);

    /**
     * 死锁测试
     */
    private static void deathLock() {
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("sh-pool-%d").build();

        // 线程 1
        Thread t1 = threadFactory.newThread(() -> {
            lock1.lock();
            try {
                log.info("{} get the lock1", Thread.currentThread().getName());
                Thread.sleep(1000);
                lock2.lock();
                log.info("{} get the lock2", Thread.currentThread().getName());
            } catch (Exception e) {
                log.error("异常1", e);
            } finally {
                lock1.unlock();
            }
        });

        // 线程 2
        Thread t2 = threadFactory.newThread(() -> {
            lock2.lock();
            try {
                log.info("{} get the lock2", Thread.currentThread().getName());
                Thread.sleep(1000);
                lock1.lock();
                log.info("{} get the lock1", Thread.currentThread().getName());
            } catch (Exception e) {
                log.error("异常1", e);
            } finally {
                lock2.unlock();
            }
        });

        t1.setName("thread-t");
        t2.setName("thread-h");

        t1.start();
        t2.start();
    }

}
